using System;

namespace HalconDotNet
{
	internal class HTupleMixed : HTupleImplementation
	{
		protected object[] o;

		public override object[] OArr
		{
			get
			{
				return o;
			}
			set
			{
				SetArray(value, copy: false);
			}
		}

		public override HTupleType Type => HTupleType.MIXED;

		protected override Array CreateArray(int size)
		{
			object[] array = new object[size];
			for (int i = 0; i < size; i++)
			{
				array[i] = 0;
			}
			return array;
		}

		protected override void NotifyArrayUpdate()
		{
			o = (object[])data;
		}

		public HTupleMixed(HTupleImplementation data)
			: this(data.ToOArr(), copy: false)
		{
		}

		public HTupleMixed(object o)
			: this(new object[1]
			{
				o
			}, copy: false)
		{
		}

		public HTupleMixed(object[] o, bool copy)
		{
			if (copy)
			{
				object[] array = new object[o.Length];
				for (int i = 0; i < o.Length; i++)
				{
					if (o[i] != null)
					{
						int objectType = HTupleImplementation.GetObjectType(o[i]);
						if (objectType == 31 || (objectType & 0x8000) > 0)
						{
							throw new HTupleAccessException("Encountered invalid data types when creating HTuple");
						}
						if (objectType == 16)
						{
							array[i] = new HHandle((HHandle)o[i]);
						}
						else
						{
							array[i] = o[i];
						}
					}
				}
				SetArray(array, copy: false);
				return;
			}
			for (int j = 0; j < o.Length; j++)
			{
				if (o[j] != null)
				{
					int objectType2 = HTupleImplementation.GetObjectType(o[j]);
					if (objectType2 == 31 || (objectType2 & 0x8000) > 0)
					{
						throw new HTupleAccessException("Encountered invalid data types when creating HTuple");
					}
				}
			}
			SetArray(o, copy: false);
		}

		public override HTupleElements GetElement(int index, HTuple parent)
		{
			return new HTupleElements(parent, this, index);
		}

		public override HTupleElements GetElements(int[] indices, HTuple parent)
		{
			if (indices == null || indices.Length == 0)
			{
				return new HTupleElements();
			}
			return new HTupleElements(parent, this, indices);
		}

		public override void SetElements(int[] indices, HTupleElements elements)
		{
			HTupleElementsMixed hTupleElementsMixed = new HTupleElementsMixed(this, indices);
			hTupleElementsMixed.setO(elements.OArr);
		}

		public override void Dispose()
		{
			for (int i = 0; i < base.Length; i++)
			{
				if (GetElementType(i) == HTupleType.HANDLE)
				{
					((HHandle)o[i]).Dispose();
				}
			}
		}

		public HTupleType GetElementType(int index)
		{
			return (HTupleType)HTupleImplementation.GetObjectType(o[index]);
		}

		public HTupleType GetElementType(int[] indices)
		{
			if (indices == null || indices.Length == 0)
			{
				return HTupleType.EMPTY;
			}
			HTupleType objectType = (HTupleType)HTupleImplementation.GetObjectType(o[indices[0]]);
			for (int i = 1; i < indices.Length; i++)
			{
				HTupleType objectType2 = (HTupleType)HTupleImplementation.GetObjectType(o[indices[i]]);
				if (objectType2 != objectType)
				{
					return HTupleType.MIXED;
				}
			}
			return objectType;
		}

		public override HHandle[] ToHArr()
		{
			for (int i = 0; i < base.Length; i++)
			{
				if (GetElementType(i) != HTupleType.HANDLE)
				{
					throw new HTupleAccessException(this, "Copy of mixed tuple is only allowed with handle types");
				}
			}
			HHandle[] array = new HHandle[base.Length];
			for (int j = 0; j < base.Length; j++)
			{
				array[j] = new HHandle((HHandle)o[j]);
			}
			return array;
		}

		public override object[] ToOArr()
		{
			object[] array = new object[iLength];
			CopyToOArr(array, 0);
			return array;
		}

		public override int CopyToOArr(object[] dst, int offset)
		{
			for (int i = 0; i < iLength; i++)
			{
				if (o[i] is HHandle)
				{
					dst[i + offset] = new HHandle((HHandle)o[i]);
				}
				else
				{
					dst[i + offset] = o[i];
				}
			}
			return iLength;
		}

		public override int CopyFrom(HTupleImplementation impl, int offset)
		{
			return impl.CopyToOArr(o, offset);
		}

		protected override void StoreData(IntPtr proc, IntPtr tuple)
		{
			for (int i = 0; i < iLength; i++)
			{
				switch (HTupleImplementation.GetObjectType(o[i]))
				{
				case 1:
					HalconAPI.HCkP(proc, HalconAPI.SetI(tuple, i, (int)o[i]));
					break;
				case 129:
					HalconAPI.HCkP(proc, HalconAPI.SetL(tuple, i, (long)o[i]));
					break;
				case 2:
					HalconAPI.HCkP(proc, HalconAPI.SetD(tuple, i, (double)o[i]));
					break;
				case 4:
					HalconAPI.HCkP(proc, HalconAPI.SetS(tuple, i, (string)o[i], force_utf8: false));
					break;
				case 16:
					HalconAPI.HCkP(proc, HalconAPI.SetH(tuple, i, (HHandle)o[i]));
					break;
				}
			}
		}

		public static int Load(IntPtr tuple, out HTupleMixed data, bool force_utf8)
		{
			int num = 2;
			HalconAPI.GetTupleLength(tuple, out int length);
			object[] array = new object[length];
			for (int i = 0; i < length; i++)
			{
				if (HalconAPI.IsFailure(num))
				{
					continue;
				}
				HalconAPI.GetElementType(tuple, i, out HTupleType type);
				switch (type)
				{
				case HTupleType.INTEGER:
					if (HalconAPI.isPlatform64)
					{
						num = HalconAPI.GetL(tuple, i, out long longValue);
						array[i] = longValue;
					}
					else
					{
						num = HalconAPI.GetI(tuple, i, out int intValue);
						array[i] = intValue;
					}
					break;
				case HTupleType.DOUBLE:
				{
					num = HalconAPI.GetD(tuple, i, out double doubleValue);
					array[i] = doubleValue;
					break;
				}
				case HTupleType.STRING:
				{
					num = HalconAPI.GetS(tuple, i, out string stringValue, force_utf8);
					array[i] = stringValue;
					break;
				}
				case HTupleType.HANDLE:
				{
					num = HalconAPI.GetH(tuple, i, out HHandle handle);
					array[i] = handle;
					break;
				}
				}
			}
			data = new HTupleMixed(array, copy: false);
			return num;
		}
	}
}
